package cs348a.opengl.object;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;

/**
 * <code>AbstractOpenGLObject</code> is an abstract implementation of
 * an <code>OpenGLObject</code>.
 * 
 * @author H.S Kim
 */
public abstract class AbstractOpenGLObject implements OpenGLObject {
	/** The visual position of the object */
	protected float[] position = new float[3];
	
	/** The rotation of the object in degrees */
	protected float[] rotation = new float[3];
	
	/** The visual point(offset) of rotation relative to the origin of the object */
	protected float[] rotationPoint = new float[3];
	
	/** Is the object visible */
	private boolean isVisible = true;
	
	/**
	 * @see OpenGLObject#getPosition()
	 */
	public float[] getPosition(){
		return position.clone();
	}
	
	/**
	 * @see OpenGLObject#setPosition(float[])
	 */
	public void setPosition(float[] p){
		position = p.clone();
	}
	
	/**
	 * @see OpenGLObject#getRotation()
	 */
	public float[] getRotation(){
		return rotation.clone();
	}
	
	/**
	 * @see OpenGLObject#setRotation(float[])
	 */
	public void setRotation(float[] r){
		rotation = r.clone();
	}
	
	/**
	 * @see OpenGLObject#getRotationPoint()
	 */
	public float[] getRotationPoint(){
		return rotationPoint.clone();
	}
	
	/**
	 * @see OpenGLObject#setRotationPoint(float[])
	 */
	public void setRotationPoint(float[] p){
		rotationPoint = p.clone();
	}

	/**
	 * @see OpenGLObject#setVisible(boolean)
	 */
	public void setVisible(boolean visible){
		isVisible = visible;
	}

	/**
	 * @see OpenGLObject#isVisible()
	 */
	public boolean isVisible(){
		return isVisible;
	}

	/**
	 * @see OpenGLObject#displayComponent(GLAutoDrawable)
	 */
	public void displayComponent(GLAutoDrawable drawable) {
		if(isVisible){
			GL gl = drawable.getGL();
			
			// move to position
			gl.glTranslatef(position[0], position[1], position[2]);
			
			// this rotation code loses symmetry
			// move to rotation point
			gl.glTranslatef(rotationPoint[0], rotationPoint[1], rotationPoint[2]);
			// rotate
			gl.glRotatef(rotation[1], 0, 1, 0);
			gl.glRotatef(rotation[0], 1, 0, 0);
			gl.glRotatef(rotation[2], 0, 0, 1);
			// move back to origin
			gl.glTranslatef(-rotationPoint[0], -rotationPoint[1], -rotationPoint[2]);
			
			drawComponent(drawable);
			
			// change color back to default white
			gl.glColor3f(1, 1, 1);
			
			// move to rotation point
			gl.glTranslatef(rotationPoint[0], rotationPoint[1], rotationPoint[2]);
			// reset the rotation
			gl.glRotatef(-rotation[2], 0, 0, 1);
			gl.glRotatef(-rotation[0], 1, 0, 0);
			gl.glRotatef(-rotation[1], 0, 1, 0);
			// move back to origin
			gl.glTranslatef(-rotationPoint[0], -rotationPoint[1], -rotationPoint[2]);
			
			// go back to origin
			gl.glTranslatef(-position[0], -position[1], -position[2]);
		}
	}
	
	/**
	 * Draw the component here
	 * 
	 * @param drawable
	 */
	abstract protected void drawComponent(GLAutoDrawable drawable);
}
